home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / online / source / c / compilers / Bob 1.5.sit.hqx / Bob 1.5 / Bobscn.c < prev    next >
Text File  |  1991-10-09  |  8KB  |  430 lines

  1. /* bobscn.c - a lexical scanner */
  2. /*
  3.     Copyright (c) 1991, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include <setjmp.h>
  8. #include "bob.h"
  9. #include "bobcom.h"
  10.  
  11. /* useful definitions */
  12. #define LSIZE    200
  13.  
  14. /* keyword table */
  15. static struct { char *kt_keyword; int kt_token; } ktab[] = {
  16. { "class",    T_CLASS        },
  17. { "static",    T_STATIC    },
  18. { "if",        T_IF        },
  19. { "else",    T_ELSE        },
  20. { "while",    T_WHILE        },
  21. { "return",    T_RETURN    },
  22. { "for",    T_FOR        },
  23. { "break",    T_BREAK        },
  24. { "continue",     T_CONTINUE    },
  25. { "do",        T_DO        },
  26. { "new",    T_NEW        },
  27. { "nil",    T_NIL        },
  28. { NULL,        0        }};
  29.  
  30. /* token name table */
  31. static char *t_names[] = {
  32. "<string>",
  33. "<identifier>",
  34. "<number>",
  35. "class",
  36. "static",
  37. "if",
  38. "else",
  39. "while",
  40. "return",
  41. "for",
  42. "break",
  43. "continue",
  44. "do",
  45. "new",
  46. "nil",
  47. "<=",
  48. "==",
  49. "!=",
  50. ">=",
  51. "<<",
  52. ">>",
  53. "&&",
  54. "||",
  55. "++",
  56. "--",
  57. "+=",
  58. "-=",
  59. "*=",
  60. "/=",
  61. "%=",
  62. "&=",
  63. "|=",
  64. "^=",
  65. "<<=",
  66. ">>=",
  67. "::",
  68. "->"};
  69.  
  70. /* global variables */
  71. int t_value;        /* numeric value */
  72. char t_token[TKNSIZE+1];/* token string */
  73.  
  74. /* local variables */
  75. #ifdef __STDC__
  76. static int (*getcf)(void *);    /* getc function */
  77. #else
  78. static int (*getcf)();        /* getc function */
  79. #endif
  80. static void *getcd;    /* getc data */
  81. static int savetkn;    /* look ahead token */
  82. static int savech;    /* look ahead character */
  83. static int lastch;    /* last input character */
  84. static char line[LSIZE];/* last input line */
  85. static char *lptr;    /* line pointer */
  86. static int lnum;    /* line number */
  87.  
  88. /* prototypes */
  89. #ifdef __STDC__
  90. static int rtoken(void);
  91. static int getstring(void);
  92. static int getcharacter(void);
  93. static int literalch(void);
  94. static int getid(int ch);
  95. static int getnumber(int ch);
  96. static int skipspaces(void);
  97. static int isidchar(int ch);
  98. static int getch(void);
  99. #endif
  100.  
  101. /* init_scanner - initialize the scanner */
  102. init_scanner(gf,gd)
  103. #ifdef __STDC__
  104.   int (*gf)(void *);
  105. #else
  106.   int (*gf)();
  107. #endif
  108.   void *gd;
  109. {
  110.     /* remember the getc function and data */
  111.     getcf = gf; getcd = gd;
  112.  
  113.     /* setup the line buffer */
  114.     lptr = line; *lptr = '\0';
  115.     lnum = 0;
  116.  
  117.     /* no lookahead yet */
  118.     savetkn = T_NOTOKEN;
  119.     savech = '\0';
  120.  
  121.     /* no last character */
  122.     lastch = '\0';
  123. }
  124.  
  125. /* token - get the next token */
  126. int token()
  127. {
  128.     int tkn;
  129.  
  130.     if ((tkn = savetkn) != T_NOTOKEN)
  131.     savetkn = T_NOTOKEN;
  132.     else
  133.     tkn = rtoken();
  134.     return (tkn);
  135. }
  136.  
  137. /* stoken - save a token */
  138. stoken(tkn)
  139.   int tkn;
  140. {
  141.     savetkn = tkn;
  142. }
  143.  
  144. /* tkn_name - get the name of a token */
  145. char *tkn_name(tkn)
  146.   int tkn;
  147. {
  148.     static char tname[2];
  149.     if (tkn == T_EOF)
  150.     return ("<eof>");
  151.     else if (tkn >= _TMIN && tkn <= _TMAX)
  152.     return (t_names[tkn-_TMIN]);
  153.     tname[0] = tkn;
  154.     tname[1] = '\0';
  155.     return (tname);
  156. }
  157.  
  158. /* rtoken - read the next token */
  159. static int rtoken()
  160. {
  161.     int ch,ch2;
  162.  
  163.     /* check the next character */
  164.     for (;;)
  165.     switch (ch = skipspaces()) {
  166.     case EOF:    return (T_EOF);
  167.     case '"':    return (getstring());
  168.     case '\'':    return (getcharacter());
  169.     case '<':    switch (ch = getch()) {
  170.             case '=':
  171.                 return (T_LE);
  172.             case '<':
  173.                 if ((ch = getch()) == '=')
  174.                 return (T_SHLEQ);
  175.                 savech = ch;
  176.                 return (T_SHL);
  177.             default:
  178.                 savech = ch;
  179.                 return ('<');
  180.             }
  181.     case '=':    if ((ch = getch()) == '=')
  182.                 return (T_EQ);
  183.             savech = ch;
  184.             return ('=');
  185.     case '!':    if ((ch = getch()) == '=')
  186.                 return (T_NE);
  187.             savech = ch;
  188.             return ('!');
  189.     case '>':    switch (ch = getch()) {
  190.             case '=':
  191.                 return (T_GE);
  192.             case '>':
  193.                 if ((ch = getch()) == '=')
  194.                 return (T_SHREQ);
  195.                 savech = ch;
  196.                 return (T_SHR);
  197.             default:
  198.                 savech = ch;
  199.                 return ('>');
  200.             }
  201.     case '&':    switch (ch = getch()) {
  202.             case '&':
  203.                 return (T_AND);
  204.             case '=':
  205.                 return (T_ANDEQ);
  206.             default:
  207.                 savech = ch;
  208.                 return ('&');
  209.             }
  210.     case '|':    switch (ch = getch()) {
  211.             case '|':
  212.                 return (T_OR);
  213.             case '=':
  214.                 return (T_OREQ);
  215.             default:
  216.                 savech = ch;
  217.                 return ('|');
  218.             }
  219.     case '^':    if ((ch = getch()) == '=')
  220.                 return (T_XOREQ);
  221.             savech = ch;
  222.             return ('^');
  223.     case '+':    switch (ch = getch()) {
  224.             case '+':
  225.                 return (T_INC);
  226.             case '=':
  227.                 return (T_ADDEQ);
  228.             default:
  229.                 savech = ch;
  230.                 return ('+');
  231.             }
  232.     case '-':    switch (ch = getch()) {
  233.             case '-':
  234.                 return (T_DEC);
  235.             case '=':
  236.                 return (T_SUBEQ);
  237.             case '>':
  238.                 return (T_MEMREF);
  239.             default:
  240.                 savech = ch;
  241.                 return ('-');
  242.             }
  243.     case '*':    if ((ch = getch()) == '=')
  244.                 return (T_MULEQ);
  245.             savech = ch;
  246.             return ('*');
  247.     case '/':    switch (ch = getch()) {
  248.             case '=':
  249.                 return (T_DIVEQ);
  250.             case '/':
  251.                 while ((ch = getch()) != EOF)
  252.                 if (ch == '\n')
  253.                     break;
  254.                 break;
  255.             case '*':
  256.                 ch = ch2 = EOF;
  257.                 for (; (ch2 = getch()) != EOF; ch = ch2)
  258.                 if (ch == '*' && ch2 == '/')
  259.                     break;
  260.                 break;
  261.             default:
  262.                 savech = ch;
  263.                 return ('/');
  264.             }
  265.             break;
  266.     case ':':    if ((ch = getch()) == ':')
  267.                 return (T_CC);
  268.             savech = ch;
  269.             return (':');
  270.     default:    if (isdigit(ch))
  271.                 return (getnumber(ch));
  272.             else if (isidchar(ch))
  273.                 return (getid(ch));
  274.             else {
  275.                 t_token[0] = ch;
  276.                 t_token[1] = '\0';
  277.                 return (ch);
  278.             }
  279.     }
  280. }
  281.  
  282. /* getstring - get a string */
  283. static int getstring()
  284. {
  285.     char *p;
  286.     int ch;
  287.  
  288.     /* get the string */
  289.     p = t_token;
  290.     while ((ch = literalch()) != EOF && ch != '"')
  291.     *p++ = ch;
  292.     if (ch == EOF)
  293.     savech = EOF;
  294.     *p = '\0';
  295.     return (T_STRING);
  296. }
  297.  
  298. /* getcharacter - get a character constant */
  299. static int getcharacter()
  300. {
  301.     t_value = literalch();
  302.     t_token[0] = t_value;
  303.     t_token[1] = '\0';
  304.     if (getch() != '\'')
  305.     parse_error("Expecting a closing single quote");
  306.     return (T_NUMBER);
  307. }
  308.  
  309. /* literalch - get a character from a literal string */
  310. static int literalch()
  311. {
  312.     int ch;
  313.     if ((ch = getch()) == '\\')
  314.     switch (ch = getch()) {
  315.     case 'n':  ch = '\n'; break;
  316.     case 't':  ch = '\t'; break;
  317.     case EOF:  ch = '\\'; savech = EOF; break;
  318.     }
  319.     return (ch);
  320. }
  321.  
  322. /* getid - get an identifier */
  323. static int getid(ch)
  324.   int ch;
  325. {
  326.     char *p;
  327.     int i;
  328.  
  329.     /* get the identifier */
  330.     p = t_token; *p++ = ch;
  331.     while ((ch = getch()) != EOF && isidchar(ch))
  332.     *p++ = ch;
  333.     savech = ch;
  334.     *p = '\0';
  335.  
  336.     /* check to see if it is a keyword */
  337.     for (i = 0; ktab[i].kt_keyword != NULL; ++i)
  338.     if (strcmp(ktab[i].kt_keyword,t_token) == 0)
  339.         return (ktab[i].kt_token);
  340.     return (T_IDENTIFIER);
  341. }
  342.  
  343. /* getnumber - get a number */
  344. static int getnumber(ch)
  345.   int ch;
  346. {
  347.     char *p;
  348.  
  349.     /* get the number */
  350.     p = t_token; *p++ = ch; t_value = ch - '0';
  351.     while ((ch = getch()) != EOF && isdigit(ch)) {
  352.     t_value = t_value * 10 + ch - '0';
  353.     *p++ = ch;
  354.     }
  355.     savech = ch;
  356.     *p = '\0';
  357.     return (T_NUMBER);
  358. }
  359.  
  360. /* skipspaces - skip leading spaces */
  361. static skipspaces()
  362. {
  363.     int ch;
  364.     while ((ch = getch()) != '\0' && isspace(ch))
  365.     ;
  366.     return (ch);
  367. }
  368.  
  369. /* isidchar - is this an identifier character */
  370. static int isidchar(ch)
  371.   int ch;
  372. {
  373.     return (isupper(ch)
  374.          || islower(ch)
  375.          || isdigit(ch)
  376.          || ch == '_');
  377. }
  378.  
  379. /* getch - get the next character */
  380. static int getch()
  381. {
  382.     int ch;
  383.     
  384.     /* check for a lookahead character */
  385.     if ((ch = savech) != '\0')
  386.     savech = '\0';
  387.  
  388.     /* check for a buffered character */
  389.     else {
  390.     while ((ch = *lptr++) == '\0') {
  391.  
  392.         /* check for being at the end of file */
  393.         if (lastch == EOF)
  394.         return (EOF);
  395.  
  396.         /* read the next line */
  397.         lptr = line;
  398.         while ((lastch = (*getcf)(getcd)) != EOF && lastch != '\n')
  399.         *lptr++ = lastch;
  400.         *lptr++ = '\n'; *lptr = '\0';
  401.         lptr = line;
  402.         ++lnum;
  403.     }
  404.     }
  405.  
  406.     /* return the current character */
  407.     return (ch);
  408. }
  409.  
  410. /* parse_error - report an error in the current line */
  411. parse_error(msg)
  412.   char *msg;
  413. {
  414.     extern jmp_buf error_trap;
  415.     char buf[LSIZE],*src,*dst;
  416.  
  417.     /* redisplay the line with the error */
  418.     sprintf(buf,">>> %s <<<\n>>> in line %d <<<\n%s",msg,lnum,line);
  419.     osputs(buf);
  420.  
  421.     /* point to the position immediately following the error */
  422.     for (src = line, dst = buf; src < lptr-1; ++src)
  423.     *dst++ = (*src == '\t' ? '\t' : ' ');
  424.     *dst++ = '^'; *dst++ = '\n'; *dst = '\0';
  425.     osputs(buf);
  426.  
  427.     /* invoke the error trap */
  428.     longjmp(error_trap,1);
  429. }
  430.